package com.kuaimacode.kframework.api.controller.user;

import com.github.pagehelper.PageInfo;
import com.kuaimacode.kframework.api.controller.BaseController;
import com.kuaimacode.kframework.api.service.*;
import com.kuaimacode.kframework.api.service.category.AgentServService;
import com.kuaimacode.kframework.api.service.config.SysAgentWeatherService;
import com.kuaimacode.kframework.api.service.sys.AgentOrderRewardService;
import com.kuaimacode.kframework.api.service.user.OrderDispatchService;
import com.kuaimacode.kframework.api.service.user.OrderService;
import com.kuaimacode.kframework.api.vo.request.CancleOrderReq;
import com.kuaimacode.kframework.api.vo.request.NightWeatherOrderReq;
import com.kuaimacode.kframework.api.vo.response.ComplainMasterResp;
import com.kuaimacode.kframework.api.vo.response.UserPartnerResp;
import com.kuaimacode.kframework.common.Constant;
import com.kuaimacode.kframework.common.JsonResult;
import com.kuaimacode.kframework.component.ComponentUtil;
import com.kuaimacode.kframework.constants.PageConstants;
import com.kuaimacode.kframework.exception.ErrorEnum;
import com.kuaimacode.kframework.exception.ServerInternalErrorException;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgent;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgentCategoryCfg;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgentWeather;
import com.kuaimacode.kframework.mybatis.models.category.AgentServ;
import com.kuaimacode.kframework.mybatis.models.coupon.UserCoupon;
import com.kuaimacode.kframework.mybatis.models.holiday.Holiday;
import com.kuaimacode.kframework.mybatis.models.master.MasterOrderAccitity;
import com.kuaimacode.kframework.mybatis.models.sys.AgentOrderReward;
import com.kuaimacode.kframework.mybatis.models.user.*;
import com.kuaimacode.kframework.util.CommonUtil;
import com.kuaimacode.kframework.util.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 中元
 * @date 2019/03/18
 */
@RestController
@RequestMapping("/order")
@Api(tags = "订单",description = "订单相关api")
public class OrderController extends BaseController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private AgentService agentService;
    @Autowired
    private SysAgentCategoryCfgService sysAgentCategoryCfgService;
    @Autowired
    private SysAgentWeatherService sysAgentWeatherService;
    @Autowired
    private UserCouponService userCouponService;
    @Autowired
    private FeedbackService feedbackService;
    @Autowired
    private AgentServService agentServService;
  /*  @Autowired
    private AlipayController alipayController;
    @Autowired
    private WxpayController wxpayController;*/
    @Autowired
    private UserService userService;
    @Autowired
    private AgentOrderRewardService agentOrderRewardService;
    @Autowired
    private HolidayService holidayService;
    @Autowired
    private ComponentUtil componentUtil;

    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private UserAccountDetailService detailService;
    @Autowired
    private MasterOrderAccitityService accitityService;
    @Autowired
    private UserMasterService masterService;
    @Autowired
    private UploadService uploadService;
    @Autowired
    private SysParamService sysParamService;
    @Autowired
    private OrderDispatchService orderDispatchService;

    @Autowired
    private UserAccountDetailService userAccountDetailService;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @ApiOperation(value = "查询订单列表", notes="查询订单列表[订单状态：-1-全部订单，0-投诉订单 1-待支付 2-待接单 3-服务中 4-取货中  5-送货中 6-待评价 7-已完成 8-已取消 20-订单服务中（包含3/4/5状态）,[跑腿有取送货状态，技术服务接单后是服务中]]")
    @GetMapping("/list/{status}")
    @ApiImplicitParam(name = "status", value = "订单状态", required = false, dataType = "integer",paramType = "path")
    public JsonResult<OrderSimple> list(@PathVariable Integer status,
                           @RequestParam(value = "pageNum", required = true, defaultValue = PageConstants.PAGE_NUM+"") int pageNum,
                           @RequestParam(value = "pageSize", required = true, defaultValue = PageConstants.PAGE_SIZE+"") int pageSize){

        if(status == 0 ){
            //查询投诉订单
            PageInfo<OrderSimple> list = feedbackService.queryOdersByUserId(getUserId(), Constant.FeedbackTypeEnum.COMPLAIN.getCode(), pageNum, pageSize);
            return JsonResult.success(list);
        }/*else if(status == 20){
            //查询订单服务中的状态，包含3、4、5
            //查询其他类型订单,type为空查全部
            PageInfo<OrderSimple> list  = orderService.queryAllOrders(getUserId(), status, null, pageNum, pageSize);
            //PageInfo<Order> list  = orderService.getOrderList(getUserId(), type, pageNum, pageSize);
            return JsonResult.success(list);
        }else*/{
            //查询其他类型订单,type为空查全部
            PageInfo<OrderSimple> list  = orderService.queryAllOrders(getUserId(), status, null, pageNum, pageSize, null);
            //PageInfo<Order> list  = orderService.getOrderList(getUserId(), type, pageNum, pageSize);
            return JsonResult.success(list);
        }

    }

    /*@ApiOperation(value = "编辑订单", notes="编辑订单")
    @PostMapping("/edit")
    @ApiImplicitParams({
        //@ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "long",paramType = "path"),
        @ApiImplicitParam(name = "order", value = "Order实体", required = true, dataType = "Order")
    })
    public JsonResult edit(@RequestBody Order order, HttpServletRequest request){
        //order.setUserId(getUserId());
        if(orderService.updateById(order)){
            return JsonResult.success();
        }else{
            return JsonResult.failure("操作失败");
        }

    }*/

    @ApiOperation(value = "新增订单", notes="下单接口,必传字段为[分站id-agentId;普通订单：订单距离-distance，分类id-categoryId，订单类型-type，订单子类型-childType, （如果是技术服务类订单，masterId必传）起始地址-fromAddressId, 目的地址-toAddressId, 发货时间-taskTime(例如：2019-03-21T07:04:42.175Z)，是否立即发货-hasInstant(1-是 0-否)；合作商家订单：是否合作商家订单-hasPartner（固定传1），订单数量-partnerNumber],是否立即发货-hasInstant(1-是 0-否),非必传字段为[普通订单：备注-remark, 优惠券id-couponId,技术服务图片-images（万能帮办时可以上传，例： 201832232.jpg,201832232.jpg），预计送达时间-forecastDeliveryTime，商品费用-goodsAmount（随意购的时候可以上送）合作商家订单：taskTime-发货时间, remark-备注],返回字段说明：[普通订单：orderNo-订单号，{orderDistance-订单距离,basicFreightFee-基础运费，specialWeatherFee-特殊天气费用，specialWeatherInfo-特殊天气说明，LateNightFee-深夜服务费，<br/>LateNightStart-深夜服务开始时间，LateNightEnd-深夜服务结束时间，insuranceFee-保价费用，insuranceRate-保价费率，collectionFee-代收款手续费，collectionRate-代收款费率，coupon-优惠券金额，couponType-优惠券类型,totalAmt-总金额 , anyHelpFee-万能帮办费用（定价时）, onSiteServiceFee-万能帮办上门费用（不定价时）;合作商家订单：partnerPerAmount-合作订单每笔金额, partnerNumber-合作订单笔数，其他同前;}]")
    @PostMapping("/add")
    @ApiImplicitParam(name = "order", value = "Order实体", required = true, dataType = "Order")
    @Transactional
    public JsonResult add(@RequestBody Order order, HttpServletRequest request){
        //1.信息校验
        order.validateInfo();
        orderService.valideAddress(order);//校验地址信息

        //2.获取agentId
        //Long agentId = Long.parseLong(getAgentId());
        //order.setAgentId(getAgentId());
        if(Constant.OrderTypeEnum.PAO_TUI.getCode() != order.getType() && getUserId() == order.getMasterId()){
            //万能帮办不能选择本人服务
            throw new ServerInternalErrorException(ErrorEnum.NOT_CHOOSE_SELF);
        }

        //3.生成费用明细(计算服务费并校验)*/
        Map<String,Object> costsDetail = getOrderFeeDetail(order, false);

        //4.生成订单号
        String orderNo = CommonUtil.generateOrderNo(Constant.ORDER_PRE, getUserId());
        String outTradeNo = CommonUtil.generateOrderNum(Constant.OUT_TRADE_NO_PRE, getUserId());

        if(order.getCollectionAmount() != null && order.getCollectionAmount().compareTo(BigDecimal.ZERO)>0){
            //如果有代收货款
            String collectionOutTradeNo = CommonUtil.generateOrderNum(Constant.COLLECTION_OUT_TRADE_NO_PRE, getUserId());
            order.setCollectionOutTradeNo(collectionOutTradeNo);
            order.setCollectionPayStatus(Constant.CollectionPayStatusEnum.NOT_PAY.getCode());
        }

        if(order.getType() != Constant.OrderTypeEnum.PAO_TUI.getCode() && order.getPriceWay() == Constant.PriceWayEnum.NOT_SURE_PRICE.getCode()){
            //如果是技术服务不定价
            String feeOutTradeNo = CommonUtil.generateOrderNum(Constant.FEE_OUT_TRADE_NO_PRE, getUserId());
            order.setFeeOutTradeNo(feeOutTradeNo);
            order.setFeePayStatus(Constant.CollectionPayStatusEnum.NOT_PAY.getCode());
        }

        //5.填充其他信息
        order.setId(null);//id自动生成
        order.setOrderNo(orderNo);//订单号
        order.setOutTradeNo(orderNo);//订单支付唯一识别码
        //order.setOutTradeNo(outTradeNo);//订单支付唯一识别码
        order.setCreateAt(new Date());
        order.setDeleteState(Constant.DeleteStateEnum.NORMAL.getCode());
        order.setStatus(Constant.OrderStatusEnum.WAIT_PAY.getCode());
        order.setUserId(getUserId());//用户信息
        detailTemplate(order);//记录订单详情模板类型
        if(orderService.save(order)){
            if(order.getCouponId() !=null){
                //优惠券使用
                UserCoupon userCoupon = userCouponService.getById(order.getCouponId());
                if(userCoupon == null ){
                    throw new ServerInternalErrorException(ErrorEnum.COUPON_INFO_NOT_EXIST);
                }
                //已使用状态
                userCoupon.setState(Integer.parseInt(Constant.COUPON_STATUS_USED));
                Boolean flag = userCouponService.updateById(userCoupon);
                if(!flag){
                    throw new ServerInternalErrorException(ErrorEnum.COUPON_INFO_NOT_EXIST);
                }
            }
            //返回信息
            Map<String,Object> rslt = new HashMap<String,Object>();
            rslt.put("orderNo",orderNo);
            rslt.put("orderId",order.getId());
            rslt.put("feeDetail",costsDetail);
            return JsonResult.success(rslt);
        }else{
            return JsonResult.failure("操作失败");
        }

    }

    @ApiOperation(value = "查询订单费用明细", notes="查询费用明细分两种情况，一种是下单后，必传字段为[订单号=orderNo]；另一种情况是下单前必传字段为[分站id-agentId；普通订单：订单距离-distance，分类id-categoryId，订单类型-type，订单子类型-childType，weight-重量（帮我送、帮我取必填）；合作商家订单：是否合作商家订单-hasPartner（固定传1），订单数量-partnerNumber],非必填字段[普通订单：优惠券id-couponId，商品费用-goodsAmount（随意购的时候可以上送），代收款-collectionAmount，保价金额-insurance；合作商家订单：taskTime-发货时间, remark-备注],<br/>返回字段说明：[普通订单：orderDistance-订单距离,basicFreightFee-基础运费，specialWeatherFee-特殊天气费用，specialWeatherInfo-特殊天气说明，LateNightFee-深夜服务费，LateNightStart-深夜服务开始时间，LateNightEnd-深夜服务结束时间，insuranceFee-保价费用，insuranceRate-保价费率，collectionFee-代收款手续费，collectionRate-代收款费率，coupon-优惠券金额，couponType-优惠券类型,totalAmt-总金额,overWeightFee-超重费用，overWeightPrice-超重后每公斤单价，overWeightBegin-超重开始重量，overWeightEnd-超重结束重量，onSiteServiceFee-服务费（万能帮办），goodsAmount-商品费用（随意购时）, anyHelpFee-万能帮办费用（定价时）, onSiteServiceFee-万能帮办上门费用（不定价时）;合作商家订单：partnerPerAmount-合作订单每笔金额, partnerNumber-合作订单笔数，其他同前]")
    @PostMapping("/feeDetail")
    @ApiImplicitParam(name = "order", value = "Order实体", required = true, dataType = "Order")
    public JsonResult feeDetail(@RequestBody Order order){
        //如果传了orderNo,其他字段可不传
        Boolean hasAddOrder = false;
        if(order.getOrderNo() != null &&  !"".equals(order.getOrderNo())){
            order = orderService.findOrderByOrderNo(order.getOrderNo());
            if(order == null){
                throw new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST);
            }
            hasAddOrder = true;
        }else{
            //获取agentId
           // Long agentId = Long.parseLong(getAgentId());
            //order.setAgentId(getAgentId());
            if(order.getAgentId() == null || StringUtils.isBlank(order.getAgentId())){
                throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
            }
        }
        //1.信息校验
        //order.validateInfo();
        //2.生成费用明细(计算服务费并校验)*/
        Map<String,Object> costsDetail = getOrderFeeDetail(order, hasAddOrder);
        if(costsDetail != null){
            return JsonResult.success(costsDetail);
        }else{
            return JsonResult.failure("操作失败");
        }

    }

    @ApiOperation(value = "根据Id删除订单", notes="根据Id删除订单")
    @GetMapping("/detete/{id}")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "long",paramType = "path")
    public JsonResult delete(@PathVariable Long id, HttpServletRequest request){
        try {
            Order order = orderService.getById(id);
            if (!getUserId().equals(order.getUserId())){
                return JsonResult.failure("没有操作权限");
            }
            orderService.removeById(id);
        } catch (Exception e) {
            e.printStackTrace();
            return JsonResult.failure("操作失败");
        }
        return JsonResult.success();
    }

    @ApiOperation(value = "根据ID获取订单", notes="已格式化返回数据")
    @GetMapping("/getSimpleById/{id}")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "long",paramType = "path")
    public JsonResult<OrderMore> getSimpleById(@PathVariable Long id, HttpServletRequest request){
        OrderMore order = orderService.queryOrderById(id);
        Optional.ofNullable(order).orElseThrow(()->new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST));
        //if (!getUserId().equals(order.getUserId()) ){
        //    return JsonResult.failure("没有操作权限");
       // }
        if(order.getStatus() == Constant.OrderStatusEnum.WAIT_PAY.getCode()){
            Long remainPayTime = DateUtil.timeSubMin(order.getCreateAt(),new Date());
            if(remainPayTime < 0 || remainPayTime >= 30){
                order.setRemainPayTime(0);
            }else{
                order.setRemainPayTime(30-remainPayTime.intValue());
            }
        }
        if(order.getStatus() == Constant.OrderStatusEnum.WAIT_ACCEPT.getCode()){
            Long forcastTime = DateUtil.timeSubMin(order.getUpdateAt(),new Date());
            if(forcastTime < 0 || forcastTime >= 30){
                order.setForecastDeliveryMin(0);
            }else{
                order.setForecastDeliveryMin(30-forcastTime.intValue());
            }
        }
        if(order.getStatus() > Constant.OrderStatusEnum.WAIT_ACCEPT.getCode()){
            MasterOrderAccitity accitity = accitityService.getMasterAccitityByOrderId(id, null);
            if(accitity != null){//接单时间
                order.setAcceptTime(accitity.getCreateDt());
            }
        }
        if(order.getImages() != null){
            //处理图片
            List<String> images = new ArrayList<String>();
            Arrays.stream(Optional.ofNullable(order.getImages()).get().split(",")).forEach(o->{
                images.add(componentUtil.convertImgUrl(o));
            });
            order.setImagesList(images);
        }
        if(order.getGoodsImages() != null){
            //处理图片
            List<String> images = new ArrayList<String>();
            Arrays.stream(Optional.ofNullable(order.getGoodsImages()).get().split(",")).forEach(o->{
                images.add(componentUtil.convertImgUrl(o));
            });
            order.setGoodsImagesList(images);
        }
        //处理音频
        Optional.ofNullable(order.getAudio()).ifPresent(o->order.setAudio(componentUtil.convertImgUrl(o)));

        //处理头像
        Optional.ofNullable(order).ifPresent(o->order.setMasterAvatarUrl(componentUtil.convertImgUrl(order.getMasterAvatarUrl())));

        //计算预计到达时间相关配置
        SysAgent agent = agentService.getAgentInfoById(order.getAgentId()+"");
        order.setInitKM(3);
        order.setInitTime(agent.getInitTime());
        order.setExtraTime(agent.getExtraTime());


        return JsonResult.success(order);
    }

    /*@ApiOperation(value = "根据ID获取订单", notes="未格式化返回数据")
    @GetMapping("/getById/{id}")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "long",paramType = "path")
    public JsonResult<Order> getById(@PathVariable Long id, HttpServletRequest request){
        Order order = orderService.getById(id);
        if (getUserId() != order.getUserId()){
            return JsonResult.failure("没有操作权限");
        }
        return JsonResult.success(order);
    }*/

    @ApiOperation(value = "查询是否深夜服务和特殊天气", notes="查询是否深夜服务和特殊天气,请只上送taskTime-发货时间")
    @PostMapping("/getNightWeather")
    @ApiImplicitParam(name = "order", value = "查询深夜服务特殊天气实体", required = true, dataType = "NightWeatherOrderReq")
    public JsonResult getNightWeather(@RequestBody NightWeatherOrderReq order){
        Map map = new HashMap();
        Map nightMap = new HashMap();
        Map weatherMap = new HashMap();
        String agentId = order.getAgentId();//(String)request.getSession().getAttribute("agent_id");
        if(agentId == null || StringUtils.isBlank(agentId)){
            throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
        }
        SysAgent agent = agentService.getAgentInfoById(agentId);
        if(agent == null || agent.getStat() == Constant.AgentStatEnum.OFF.getCode()){
            throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
        }
        List<SysAgentWeather> agentWeatherList = sysAgentWeatherService.getRealTimeAgentWeather(agentId);
        if(agentWeatherList != null && agentWeatherList.size() >0){
            //同一分站，同一时间 只能设置一种特殊天气
            //如果是特殊天气，记录费用及描述
            SysAgentWeather sysAgentWeather = agentWeatherList.get(0);
            weatherMap.put("weather","1");
            weatherMap.put("reward",sysAgentWeather.getReward());
            weatherMap.put("desc",sysAgentWeather.getWeatherDesc());
        }else{
            weatherMap.put("weather","0");
            weatherMap.put("award","");
            weatherMap.put("desc","");
        }

        String nightS = "",nightE = "";
        BigDecimal reward = BigDecimal.ZERO;
        if(agent != null && agent.getStat() != Constant.AgentStatEnum.OFF.getCode()){
            nightS = agent.getNightS();
            nightE = agent.getNightE();
            reward = agent.getAward();
        }

        //获取系统时间
        boolean is_night = DateUtil.isInTime(order.getTaskTime(), nightS, nightE);
        nightMap.put("nightS",nightS);
        nightMap.put("nightE",nightE);
        if(is_night){
            nightMap.put("night","1");
            nightMap.put("award",reward);
        }else{
            nightMap.put("night","0");
            nightMap.put("award","");
        }
        map.put("night",nightMap);
        map.put("weather",weatherMap);

        return JsonResult.success(map);
    }


    @ApiOperation(value = "取消订单", notes="根据ID取消订单,取消原因为可选字段（如{\"cancleRemark\":\"dddd\"}）")
    @PostMapping("/cancle/{id}")
    @ApiImplicitParam(name = "orders", value = "取消订单实体", required = false, dataType = "CancleOrderReq")
    @Transactional
    public JsonResult cancle(@PathVariable Long id, @RequestBody CancleOrderReq orders, HttpServletRequest request){
        Order order = orderService.getById(id);
        Optional.ofNullable(order).orElseThrow(()->new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST));
        if (!getUserId().equals(order.getUserId())){
            return JsonResult.failure("没有操作权限");
        }
        //取消原因
        String cancleRemark = orders.getCancleRemark();
        Integer tempStatus = order.getStatus();
        Optional.ofNullable(cancleRemark).ifPresent(str->order.setCancleRemark(cancleRemark));
        //处理取消
        if(Constant.OrderStatusEnum.WAIT_PAY.getCode() == order.getStatus()){
            //待支付
            order.setStatus(Constant.OrderStatusEnum.CANCLE.getCode());
            order.setCancleTime(new Date());
            order.setCancleBy(2);//个人取消
            order.setUpdateAt(new Date());
            if(!orderService.updateById(order)){
                return JsonResult.failure("操作失败");
            }
        }else if(Constant.OrderStatusEnum.WAIT_ACCEPT.getCode() == order.getStatus() ||
                Constant.OrderStatusEnum.SERVERING.getCode() == order.getStatus() ||
                Constant.OrderStatusEnum.FETCHING.getCode() == order.getStatus()
                || Constant.OrderStatusEnum.SENDING.getCode() == order.getStatus()
        ){
            //待接单、服务中、取货中 //、送货中 需要退款
            //if(Constant.PayTypeEnum.WXPAY.getCode() == order.getPayType()){
                //微信支付
               /* boolean flag = wxpayController.refound(order);
                if(!flag){
                    return JsonResult.failure("取消订单失败");
                }*/
              // order.setStatus(Constant.OrderStatusEnum.CANCLEING.getCode());//置为取消中，需师傅同意
           // }else if(Constant.PayTypeEnum.ALIPAY.getCode() == order.getPayType()){
                //支付宝支付退款
               /* boolean flag = alipayController.refound(order);
                if(!flag){
                    return JsonResult.failure("取消订单失败");
             //   }*/
           //     order.setStatus(Constant.OrderStatusEnum.CANCLEING.getCode());//置为取消中，需师傅同意
           // }else{
           //     throw new ServerInternalErrorException(ErrorEnum.ERROR_PAY_TYPE);
           // }



            /*//查询当前订单的流程状态
            MasterOrderAccitity accitity = accitityService.getMasterAccitityByOrderId(order.getId(), null);
            BigDecimal orderAmount = order.getAmount();
            User master = userService.getById(order.getMasterId());
            //处理优惠券
            if(order.getCouponId() !=null && order.getCouponAmount() !=null){
                //优惠券还原成未使用状态
                UserCoupon userCoupon = userCouponService.getById(order.getCouponId());
                if(userCoupon != null ){
                    userCoupon.setState(Integer.parseInt(Constant.COUPON_STATUS_NOT_USED));
                    if(userCouponService.updateById(userCoupon)){
                        orderAmount = orderAmount.subtract(order.getCouponAmount());
                    }
                }
            }
            if(orderAmount.compareTo(BigDecimal.ZERO) <= 0){
                //全额优惠券抵扣的情况
                return JsonResult.success();
            }
            if(master != null && Constant.OrderStatusEnum.SENDING.getCode() == order.getStatus() && accitity != null
                    && Integer.parseInt(MasterConstants.MasterOrderCurrentStatus.STATUS_2.getCode()) <= Integer.parseInt(accitity.getCurrentStatus())){
                //平台设置的取消订单比例
                BigDecimal sysRate = agentService.getById(order.getAgentId()).getProportion();
                if(sysRate == null || sysRate.compareTo(new BigDecimal(0.00)) == 0){
                    sysRate = new BigDecimal(0.50);//默认50%
                }
                //如果订单流程已是我已到达，则扣款sysRate%，一半给师傅，一半退到用户余额（只有送货中的订单）
                BigDecimal tempAmount = orderAmount.multiply(sysRate);
                orderAmount = orderAmount.subtract(tempAmount);
                if(orderAmount == null || orderAmount.compareTo(new BigDecimal(0.00)) == 0){
                    orderAmount = new BigDecimal(0.00);
                }
                //完成师傅余额增长
                BigDecimal balance = Optional.ofNullable(tempAmount).orElse(BigDecimal.ZERO).add(master.getAccountBalance());
                master.setAccountBalance(balance);
                if(userService.updateById(master)){
                    //保存余额变动明细
                    UserAccountDetail userAccountDetail = new UserAccountDetail();
                    userAccountDetail.setAccountType("1");
                    userAccountDetail.setAccoutWay(1L);
                    userAccountDetail.setAmount(tempAmount.toString());
                    userAccountDetail.setCreateDt(new Date());
                    userAccountDetail.setDetailType("2");
                    userAccountDetail.setInOutType("3");
                    userAccountDetail.setTranDesc("用户取消订单:"+order.getId());
                    userAccountDetail.setUserId(order.getMasterId());
                    userAccountDetail.setStatus("0");
                    userAccountDetailService.save(userAccountDetail);
                }else{
                    logger.error("用户取消订单[%s],师傅余额变动失败", order.getOrderNo());
                }
            }

            //修改用户余额
            User user = userService.getById(order.getUserId());
            Optional.ofNullable(order).orElseThrow(() -> new ServerInternalErrorException(ErrorEnum.USER_NOT_EXISTS));
            BigDecimal balance = Optional.ofNullable(orderAmount).orElse(BigDecimal.ZERO).add(user.getAccountBalance());
            user.setAccountBalance(balance);
            if (userService.updateById(user)) {
                //保存余额变动明细
                UserAccountDetail userAccountDetail = new UserAccountDetail();
                userAccountDetail.setAccountType("1");
                userAccountDetail.setAccoutWay(1L);
                userAccountDetail.setAmount(orderAmount.toString());
                userAccountDetail.setCreateDt(new Date());
                userAccountDetail.setDetailType("2");
                userAccountDetail.setInOutType("1");
                userAccountDetail.setTranDesc("订单退款:" + order.getOrderNo());
                userAccountDetail.setUserId(order.getUserId());
                userAccountDetail.setStatus("0");
                detailService.save(userAccountDetail);
                //修改订单状态
                order.setStatus(Constant.OrderStatusEnum.CANCLE.getCode());
                order.setUpdateAt(new Date());
                if(orderService.updateById(order)){
                    if(Constant.OrderStatusEnum.WAIT_ACCEPT.getCode() != tempStatus){
                        //通知推送师傅
                        if(order.getMasterId() != null) {
                            sysMessageService.saveMessage("用户取消订单", "用户因" + order.getCancleRemark()
                                    + "取消订单[" + order.getOrderNo() + "]", true, order.getMasterId());
                        }
                    }
                }
            } else {
                logger.error("用户取消订单[%s],用户余额变动失败", order.getOrderNo());
                return JsonResult.failure(ErrorEnum.SYSTEM_ERROR.getCode(), ErrorEnum.SYSTEM_ERROR.getMsg());
            }*/
            boolean flag = orderService.cancleOrder(order,false);
            if(!flag){
                return JsonResult.failure(ErrorEnum.SYSTEM_ERROR.getCode(), ErrorEnum.SYSTEM_ERROR.getMsg());
            }
        }else{
            throw new ServerInternalErrorException(ErrorEnum.ORDER_NOT_CANCLE);
        }
        return JsonResult.success();
    }


    @ApiOperation(value = "查询订单打赏配置列表", notes="查询订单打赏列表，")
    @GetMapping("/reward/{agentId}")
    @ApiImplicitParam(name = "agentId", value = "分站ID", required = true, dataType = "string",paramType = "path")
    public JsonResult<AgentOrderReward> list(@PathVariable String agentId){
        if(agentId == null || StringUtils.isBlank(agentId)){
            throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
        }
        SysAgent agent = agentService.getAgentInfoById(agentId);
        if(agent == null || agent.getStat() == Constant.AgentStatEnum.OFF.getCode()){
            throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
        }
        List<AgentOrderReward> list = agentOrderRewardService.findAllByAgentId(agentId);
        return JsonResult.success(list);
    }


    @ApiOperation(value = "查询需要弹窗的订单列表", notes="查询需要弹窗的订单列表")
    @GetMapping("/popup/{type}")
    @ApiImplicitParam(name = "type", value = "类型 1-派单 2-取消订单 3-全部", required = true, dataType = "string",paramType = "path")
    public JsonResult<AgentOrderReward> popup(@PathVariable Integer type){
        User user = userService.getById(getUserId());
        List<Map<String,Object>> list = new ArrayList<>();
        if(type == 1 || type==3){
            //派单
            String ids = user.getPopupPaidan();
            if(ids != null && ids.length()>0){
                String[] idss = ids.split(",");
                for(String orderId:idss){
                    if(orderId == null || orderId.length()==0 || "".equals(orderId)){
                        continue;
                    }
                    OrderMore om = orderService.queryOrderById(Long.parseLong(orderId));
                    OrderDispatch orderDispatch = orderDispatchService.getByOrderId(Long.parseLong(orderId), 1);//待接单
                    Map<String,Object> map = new HashMap<>();
                    if(om != null && orderDispatch != null){
                        //person-管理员派单 auto-自动派单
                        if("auto".equals(orderDispatch.getDispatchType())){
                            map.put("type", 1);//1-自动派单 2-取消 3-人工派单 4-新订单
                        }else{
                            map.put("type", 3);//1-自动派单 2-取消 3-人工派单 4-新订单
                        }
                        map.put("orderId", om.getOrderId());
                        map.put("orderNo", om.getOrderNo());
                        map.put("orderType", om.getOrderType());
                        map.put("orderTypeName", om.getOrderTypeName());
                        map.put("amount", om.getAmount());
                        map.put("orderChildType", om.getOrderChildType());
                        map.put("orderChildTypeName", om.getOrderChildTypeName());
                        map.put("fromAddress", om.getFromAddress());
                        map.put("toAddress", om.getToAddress());
                        //新增
                        map.put("hasPartner", om.getHasPartner());
                        map.put("hasInstant", om.getHasInstant());
                        map.put("hasInstantDesc", om.getHasInstantDesc());
                        map.put("categoryName", om.getCategoryName());
                        map.put("weight", om.getWeight());
                        map.put("remark", om.getRemark());
                        map.put("fromLatitude", om.getFromLatitude());
                        map.put("fromLongitude", om.getFromLongitude());
                        map.put("toLatitude", om.getToLatitude());
                        map.put("toLongitude", om.getToLongitude());
                        map.put("insurance", om.getInsurance());
                        map.put("insuranceFee", om.getInsuranceFee());
                        map.put("collectionAmount", om.getCollectionAmount());
                        //计算师傅预计收入
                        Map<String, BigDecimal> incomeMap = orderService.getIncome(om.getOrderNo());
                        if(incomeMap!=null){
                            map.put("expectedIncome", incomeMap.get("master"));
                        }else{
                            map.put("expectedIncome", "0.00");
                        }

                        map.put("title", "阿四服务新订单");
                        map.put("msg", "系统向您派送了新的订单，请及时处理。");
                        list.add(map);
                    }
                }
            }
        }
        if(type == 2 || type==3){
            //取消订单
            String ids = user.getPopupQuxiao();
            if(ids != null && ids.length()>0) {
                String[] idss = ids.split(",");
                for (String orderId : idss) {
                    if(orderId == null || orderId.length()==0 || "".equals(orderId)){
                        continue;
                    }
                    OrderMore om = orderService.queryOrderById(Long.parseLong(orderId));
                    Map<String, Object> map = new HashMap<>();
                    if (om != null) {
                        map.put("type", 2);//1-自动派单 2-取消 3-人工派单 4-新订单
                        map.put("orderId", om.getOrderId());
                        map.put("orderNo", om.getOrderNo());
                        map.put("orderType", om.getOrderType());
                        map.put("orderTypeName", om.getOrderTypeName());
                        map.put("amount", om.getAmount());
                        map.put("orderChildType", om.getOrderChildType());
                        map.put("orderChildTypeName", om.getOrderChildTypeName());
                        map.put("fromAddress", om.getFromAddress());
                        map.put("toAddress", om.getToAddress());
                        map.put("title", "用户取消订单");
                        map.put("msg", "用户取消订单[" + om.getOrderNo() + "]");
                        list.add(map);
                    }
                }
            }
        }
        return JsonResult.success(list);
    }


    @ApiOperation(value = "弹窗反馈接口", notes="在收到派单、取消订单推送，弹窗完成后调用此接口，")
    @GetMapping("/popupDone")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", required = true, dataType = "string"),
            @ApiImplicitParam(name = "type", value = "类型 1-派单 2-取消订单", required = true, dataType = "string")
    })
    public JsonResult<AgentOrderReward> popupDone(@RequestParam(value = "orderId", required = true) String orderId,
                                                  @RequestParam(value = "type", required = true) Integer type){
        User user = userService.getById(getUserId());
        List<Map<String,Object>> list = new ArrayList<>();
        if(type == 1){
            //派单
            String ids = user.getPopupPaidan();
            if(ids != null && ids.length()>0){
                String[] idss = ids.split(",");
                List<String> lists = new ArrayList<>();
                for(String id:idss){
                    if(id !=null && !id.equals(orderId) && id.length()>0){
                        lists.add(id);
                    }
                }
                String[] newIdss = new String[lists.size()];
                lists.toArray(newIdss);
                String reslt = StringUtils.join(newIdss,",");
                user.setPopupPaidan(reslt);
                userService.updateById(user);
            }
        }else if(type == 2){
            //取消订单
            String ids = user.getPopupQuxiao();
            String[] idss = ids.split(",");
            if(ids != null && ids.length()>0) {
                List<String> lists = new ArrayList<>();
                for (String id : idss) {
                    if(id !=null && !id.equals(orderId) && id.length()>0){
                        lists.add(id);
                    }
                }
                String[] newIdss = new String[lists.size()];
                lists.toArray(newIdss);
                String reslt = StringUtils.join(newIdss, ",");
                user.setPopupQuxiao(reslt);
                userService.updateById(user);
            }
        }
        return JsonResult.success(null);
    }

    /**
     * 获取订单费用明细
     * @param order
     * agentId
     * categoryId
     *did
     * couponId
     * isAddOrder  是否已下单
     * @return
     */
    public Map<String,Object> getOrderFeeDetail(Order order, boolean isAddOrder){
        //2.初始化查询参数
        SysAgent agent = agentService.getAgentInfoById(order.getAgentId());
        if(agent == null || agent.getStat() == Constant.AgentStatEnum.OFF.getCode()){
            throw new ServerInternalErrorException(ErrorEnum.AGENT_NOT_NORMAL_OR_NOT_EXIST);
        }
        //2.1查询分站配置的分类信息
        SysAgentCategoryCfg agentCategory = sysAgentCategoryCfgService.getById(order.getCategoryId());
        //查看数据是否匹配
        if(agentCategory != null && !order.getAgentId().equals(agentCategory.getAgentId())){
            throw new ServerInternalErrorException(ErrorEnum.NO_REAL_CATEGORY);
        }
        //2.2.1 查询分站配置的特殊节日
        List<Holiday> listHoliday = holidayService.getByAgent(agent.getId());
        if(listHoliday != null && listHoliday.size() >0){
            //开关
            String switchs = sysParamService.findByNameAndAgent("FEE_HOLIDAY_SWITCH",agent.getId());
            if(Constant.SYS_PARAM_SWITCH_ON.equals(switchs)) {
                //同一分站，同一时间 只能设置一个特殊节日
                Holiday holiday = listHoliday.get(0);
                order.setHolidayFee(holiday.getReward());
                //order.setOtherFeeInstruction(holidy.getDesc());
            }
        }

        //2.2查询分站配置的天气
        List<SysAgentWeather> agentWeatherList = sysAgentWeatherService.getRealTimeAgentWeather(agent.getId());
        if(agentWeatherList != null && agentWeatherList.size() >0){
            //开关
            String switchs = sysParamService.findByNameAndAgent("FEE_WEATHER_SWITCH",agent.getId());
            if(Constant.SYS_PARAM_SWITCH_ON.equals(switchs)) {
                //同一分站，同一时间 只能设置一种特殊天气
                //如果是特殊天气，记录费用及描述
                SysAgentWeather sysAgentWeather = agentWeatherList.get(0);
                order.setOtherFee(sysAgentWeather.getReward());
                order.setOtherFeeInstruction(sysAgentWeather.getWeatherDesc());
            }
        }
        //2.3查询优惠券信息
        Map couponInfo = null;
        if(order.getCouponId() != null && order.getCouponId()>0l  && !isAddOrder){
            couponInfo = userCouponService.queryUserCouponInfoById(getUserId(), order.getCouponId(), null);
            if(couponInfo == null){
                throw new ServerInternalErrorException(ErrorEnum.COUPON_INFO_NOT_EXIST);
            }else{
                String useScope = (String)couponInfo.get("use_scope");
                String useScopeChildType = (String)couponInfo.get("use_scope_child_type");
                if(!"0".equals(useScope)){//优惠券不是通用券
                    if(useScope == null ||  !useScope.equals(order.getType()+"")){//优惠券一级使用范围与type不一致
                        throw new ServerInternalErrorException(ErrorEnum.COUPON_NOT_SCOPE_TYPE);
                    }else{
                        if(useScopeChildType !=null &&  !useScopeChildType.equals(order.getChildType()+"")){
                            //优惠券二级使用范围与childType不一致
                            throw new ServerInternalErrorException(ErrorEnum.COUPON_NOT_SCOPE_TYPE);
                        }
                    }
                }
            }
        }
        //2.4 如果是万能帮办，查询配置的子类 信息
        AgentServ agentServ = null;
        if(order.getType() != null && order.getChildType() != null &&
                Constant.OrderTypeEnum.PAO_TUI.getCode() != order.getType() &&
                order.getHasPartner() != Constant.IsNotEnum.YES.getCode()
            ){
            Integer orderType = order.getType();//万能帮办子类型
            Integer orderChildType = order.getChildType();//万能帮办子类型
            agentServ = agentServService.queryServByAgentIdAndCode(order.getAgentId()+"", orderType+"", orderChildType+"");
            if(agentServ == null ){
                throw new ServerInternalErrorException(ErrorEnum.SERVICE_TYPE_NOT_EXIST);
            }
        }
        //2.5 如果是合作商家一键下单，查询用户信息
        UserPartnerResp user = null;
        if(Constant.IsOrNotEnum.IS.getCode() == order.getHasPartner() && !isAddOrder){
            user = userService.getPartner(getUserId());
        }

        //3.生成费用明细(计算服务费并校验)
        Map<String,Object> costsDetail = new HashMap<>();

        if(isAddOrder){
            //已经下单
            costsDetail = orderService.queryCosts(order, agent, agentCategory, agentServ);
        }else{

            //未下单
            costsDetail = orderService.calCosts(order, agent, agentCategory, couponInfo, agentServ, user);
        }
        return costsDetail;
    }

    @ApiOperation(value = "催单", notes="给师傅推送消息")
    @GetMapping("/remnder/{id}")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "long",paramType = "path")
    public JsonResult remnder(@PathVariable Long id){
        Order order = orderService.getById(id);
        Optional.ofNullable(order).orElseThrow(()->new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST));
        if (!getUserId().equals(order.getUserId())){
            return JsonResult.failure("没有操作权限");
        }
        if(Constant.OrderStatusEnum.SERVERING.getCode() == order.getStatus() ||
                Constant.OrderStatusEnum.FETCHING.getCode() == order.getStatus()
            || Constant.OrderStatusEnum.SENDING.getCode() == order.getStatus()
        ){
            if(order.getMasterId() != null) {
                try{
                    Map<String,Object> map = new HashMap<>();
                    if(order != null){
                        map.put("type", 5);//1-自动派单 2-取消 3-人工派单 4-新订单 5-催单
                        map.put("orderId", order.getId());
                        map.put("orderNo", order.getOrderNo());
                        map.put("orderType", order.getType());
                        map.put("orderTypeName", "");
                        map.put("amount", order.getAmount());
                        map.put("orderChildType", order.getChildType());
                        map.put("orderChildTypeName","");
                        map.put("fromAddress", "");
                        map.put("toAddress", "");
                    }
                    //通知师傅
                    sysMessageService.saveMessage("用户催单", "用户催单，订单[" + order.getOrderNo() + "]，请您加快速度！", true, order.getMasterId(), map);
                }catch (Exception e){
                    e.getStackTrace();
                    return JsonResult.failure("催单失败，请重试");
                }
            }
            return JsonResult.success();
        }else{
            return JsonResult.failure("订单不在服务中");
        }
    }

    @ApiOperation(value = "订单-查询师傅信息", notes="师傅信息")
    @GetMapping("/masterMessageOrder/{orderNo}")
    @ApiImplicitParam(name = "orderNo", value = "订单号", required = true, dataType = "String",paramType = "path")
    public JsonResult<ComplainMasterResp> masterMessage(@PathVariable String orderNo){
        Order order = orderService.findOrderByOrderNo(orderNo);
        Optional.ofNullable(order).orElseThrow(()->new ServerInternalErrorException(ErrorEnum.ORDER_NOT_EXIST));
        Long masterId = order.getMasterId();
        if (masterId == null||masterId==0){
            return JsonResult.failure("该订单没有指定过师傅");
        }
        ComplainMasterResp masterResp = masterService.findMasterData(order.getMasterId());
        if (masterResp!=null && StringUtils.isNotEmpty(masterResp.getHeadPic())){
            masterResp.setHeadPic(uploadService.getPicUrlPath(masterResp.getHeadPic()));
        }
        return JsonResult.success(masterResp);
    }


    /**
     * 确定订单详情模板类型
     * @param order
     */
    private void detailTemplate(Order order){
        //1-跑腿帮我送、帮我取  2-随意购普通 3-随意购附近购买 4-技术服务类定价  5-技术服务类不定价 6 -合作商家
        if(order.getHasPartner() == Constant.IsNotEnum.YES.getCode()){
            //合作商家订单
            order.setDetailTemplate(Constant.DetailTemplateEnum.PARTNER.getCode());
        }else if(order.getType() == Constant.OrderTypeEnum.PAO_TUI.getCode()){
            //跑腿
            if(order.getChildType() == Constant.PaotuiTypeEnum.HELP_TAKE.getCode() ||
                    order.getChildType() == Constant.PaotuiTypeEnum.HELP_SEND.getCode()){
                //帮我送、帮我取
                order.setDetailTemplate(Constant.DetailTemplateEnum.HELP.getCode());
            }else{
                if (order.getFromAddressId() == null){
                    //随意购附近购买
                    order.setDetailTemplate(Constant.DetailTemplateEnum.BUY_NEARBY.getCode());
                }else{
                    //随意购普通
                    order.setDetailTemplate(Constant.DetailTemplateEnum.BUY_NORMAL.getCode());
                }
            }
        }else{
            //技术服务类型
            if (order.getPriceWay() == Constant.PriceWayEnum.SURE_PRICE.getCode()){
                //技术服务类定价
                order.setDetailTemplate(Constant.DetailTemplateEnum.TEC_PRICE_SURE.getCode());
            }else{
                //技术服务类不定价
                order.setDetailTemplate(Constant.DetailTemplateEnum.TEC_PRICE_NOSURE.getCode());
            }
        }

    }

    @ApiOperation(value = "订单取消原因", notes="订单取消原因")
    @GetMapping("/orderCancelReason")
    public JsonResult<List<?>> orderCancelReason() {
        String value = sysParamService.findByNameAndAgent("CANCEL_ORDER_OPTION", "000000");
        return JsonResult.success(Optional.ofNullable(value)
                .map(v -> Arrays.stream(v.split(",")).collect(Collectors.toList()))
                .orElse(new ArrayList<>()));
    }

}
